home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / macabuse / src / net / unix / gserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-20  |  11.5 KB  |  476 lines

  1. #include "system.h"
  2. #include "macs.hpp"
  3. #include "gserver.hpp"
  4. #include "netface.hpp"
  5. #include "timing.hpp"
  6. #include "netcfg.hpp"
  7. #include "id.hpp"
  8. #include "jwindow.hpp"
  9. #include "input.hpp"
  10. #include "dprint.hpp"
  11.  
  12. extern base_memory_struct *base;
  13. extern net_socket *comm_sock,*game_sock;
  14. extern int registered;
  15.  
  16. extern net_protocol *prot;
  17. extern join_struct *join_array;
  18. extern window_manager *eh;
  19. extern char *symbol_str(char *name);
  20. extern void service_net_request();
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <fcntl.h>
  25. #ifndef __MAC__
  26. #include <unistd.h>
  27. #include <sys/stat.h>
  28. #include <sys/types.h>
  29. #endif
  30. #include <string.h>
  31. #include <signal.h>
  32. #include "idle.hpp"
  33.  
  34. game_server::game_server()
  35. {
  36.   player_list=NULL;
  37.   waiting_server_input=1;
  38.   reload_state=0;
  39. }
  40.  
  41. int game_server::total_players()
  42. {
  43.   player_client *fl=player_list;
  44.   int total=1;
  45.   for (;fl;fl=fl->next) total++;
  46.   return total;
  47. }
  48.  
  49. void game_server::game_start_wait()
  50. {
  51.   int last_count=0;
  52.   jwindow *stat=NULL;
  53.   event ev;
  54.   int abort=0;
  55.  
  56.   while (!abort && total_players()<main_net_cfg->min_players)
  57.   {
  58.  
  59.     if (last_count!=total_players())
  60.     {
  61.       if (stat) eh->close_window(stat);
  62.       char msg[100];
  63.       sprintf(msg,symbol_str("min_wait"),main_net_cfg->min_players-total_players());
  64.       stat=eh->new_window(10,50,-1,-1,
  65.                        new info_field(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,ID_NULL,msg,
  66.                        new button(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP+eh->font()->height()*2,
  67.                           ID_CANCEL,symbol_str("cancel_button"),NULL)  ));
  68.       eh->flush_screen();
  69.       last_count=total_players();
  70.     }
  71.  
  72.     eh->flush_screen();
  73.     if (eh->event_waiting())
  74.     {
  75.       do { eh->get_event(ev); }  while (ev.type==EV_MOUSE_MOVE && eh->event_waiting()); 
  76.       if (ev.type==EV_MESSAGE && ev.message.id==ID_CANCEL)
  77.         abort=1;
  78.  
  79.  
  80.     } else
  81.       if (idle_man)
  82.         idle_man->idle();
  83.  
  84.     
  85.     service_net_request();
  86.   }
  87.  
  88.   if (idle_man)
  89.     idle_man->idle_reset();
  90.  
  91.   if (stat)
  92.   {
  93.     eh->close_window(stat);
  94.     eh->flush_screen();  
  95.   }
  96. }
  97.   
  98. game_server::player_client::~player_client()
  99. {
  100.   delete comm;
  101.   delete data_address;
  102. }
  103.  
  104. void game_server::check_collection_complete()
  105. {
  106.   player_client *c;
  107.   int got_all=waiting_server_input==0;
  108.   int add_deletes=0;
  109.   for (c=player_list;c && got_all;c=c->next)
  110.   {
  111.     if (c->delete_me())
  112.       add_deletes=1;
  113.     else if (c->has_joined() && c->wait_input())
  114.       got_all=0;
  115.   }
  116.  
  117.   if (add_deletes)
  118.   {
  119.     player_client *last=NULL;
  120.     for (c=player_list;c;)
  121.     {
  122.       if (c->delete_me())
  123.       {
  124.     base->packet.write_byte(SCMD_DELETE_CLIENT);
  125.     base->packet.write_byte(c->client_id);
  126.     if (c->wait_reload())
  127.     {
  128.       c->set_wait_reload(0);
  129.       check_reload_wait();
  130.     }
  131.  
  132.     if (last) last->next=c->next;
  133.     else player_list=c->next;
  134.     player_client *d=c;
  135.     c=c->next;
  136.     delete d;
  137.       } else 
  138.       {
  139.     last=c;
  140.     c=c->next;
  141.       }
  142.     }
  143.   }
  144.  
  145.   if (got_all)    // see if we have input from everyone, if so send it out
  146.   {   
  147.     base->packet.calc_checksum();
  148.  
  149.     for (c=player_list;c;c=c->next)      // setup for next time, wait for all the input
  150.     {
  151.       if (c->has_joined())
  152.       {
  153.     c->set_wait_input(1);      
  154.     game_sock->write(base->packet.data,base->packet.packet_size()+base->packet.packet_prefix_size(),c->data_address);
  155.  
  156.       }
  157.     }
  158.  
  159.     base->input_state=INPUT_PROCESSING; // tell engine to start processing
  160.     game_sock->read_unselectable();    // don't listen to this socket until we are prepared to read next tick's game data
  161.     waiting_server_input=1;
  162.   }  
  163. }
  164.  
  165. void game_server::add_engine_input()
  166. {
  167.   waiting_server_input=0;
  168.   base->input_state=INPUT_COLLECTING;
  169.   base->packet.set_tick_received(base->current_tick);
  170.   game_sock->read_selectable();    // we can listen for game data now that we have server input
  171.   check_collection_complete();
  172. }
  173.  
  174. void game_server::add_client_input(char *buf, int size, player_client *c)
  175. {
  176.   if (c->wait_input())  // don't add if we already have it
  177.   {
  178.     base->packet.add_to_packet(buf,size);
  179.     c->set_wait_input(0);
  180.     check_collection_complete();
  181.   }
  182. }
  183.  
  184. void game_server::check_reload_wait()
  185. {
  186.   player_client *d=player_list;
  187.   for (;d;d=d->next) 
  188.    if (d->wait_reload()) return ;    // we are still waiting for someone to reload the game 
  189.   base->wait_reload=0;
  190. }
  191.  
  192. int game_server::process_client_command(player_client *c)
  193. {
  194.   uchar cmd;
  195.   if (c->comm->read(&cmd,1)!=1) return 0;
  196.   switch (cmd)
  197.   {
  198.     case CLCMD_REQUEST_RESEND :
  199.     {
  200.       uchar tick;
  201.       if (c->comm->read(&tick,1)!=1) return 0;
  202.  
  203.       dprintf("request for resend tick %d (game cur=%d, pack=%d, last=%d)\n",
  204.           tick,base->current_tick,base->packet.tick_received(),base->last_packet.tick_received());
  205.  
  206.       if (tick==base->last_packet.tick_received())
  207.       {
  208.     net_packet *pack=&base->last_packet;      
  209.     game_sock->write(pack->data,pack->packet_size()+pack->packet_prefix_size(),c->data_address); 
  210.       }
  211.       return 1;
  212.     } break;
  213.     case CLCMD_RELOAD_START :
  214.     {
  215.       if (reload_state)   // already in reload state, notify client ok to start reloading
  216.       {
  217.         if (c->comm->write(&cmd,1)!=1) 
  218.       c->set_delete_me(1);
  219.       } else c->set_need_reload_start_ok(1);
  220.       return 1;
  221.     } break;
  222.  
  223.     case CLCMD_RELOAD_END :
  224.     {
  225.       c->set_wait_reload(0);
  226.       return 1;
  227.     } break;
  228.     case CLCMD_UNJOIN :
  229.     {
  230.       c->comm->write(&cmd,1);        // don't care weither this works or not
  231.       c->set_delete_me(1);
  232.       if (base->input_state==INPUT_COLLECTING)
  233.         check_collection_complete();
  234.     } break;
  235.   }
  236.   return 0;
  237. }
  238.  
  239.  
  240. int game_server::process_net()
  241. {
  242.   int ret=0;
  243.   /**************************       Any game data waiting?       **************************/
  244.   if ((base->input_state==INPUT_COLLECTING ||
  245.        base->input_state==INPUT_RELOAD)
  246.        && game_sock->ready_to_read())
  247.   {
  248.     net_packet tmp;
  249.     net_packet *use=&tmp;
  250.     net_address *from;
  251.     int bytes_received=game_sock->read(use->data,PACKET_MAX_SIZE,&from);
  252.  
  253.     if (from && bytes_received)
  254.     {
  255.       // make sure we got a complete packet and the packet was not a previous game tick packet
  256.       if (bytes_received==use->packet_size()+use->packet_prefix_size())
  257.       {
  258.     unsigned short rec_crc=use->get_checksum();
  259.     if (rec_crc==use->calc_checksum())
  260.     {
  261.       player_client *f=player_list,*found=NULL;
  262.       for (;!found &&f;f=f->next)
  263.       if (f->has_joined() && from->equal(f->data_address))
  264.         found=f;
  265.       if (found)
  266.       {
  267.         if (base->current_tick==use->tick_received())          
  268.         {
  269.           if (prot->debug_level(net_protocol::DB_MINOR_EVENT))
  270.             dprintf("(got data from %d)",found->client_id);
  271.  
  272. //          dprintf("(got packet %d)\n",use->tick_received()); 
  273. //          { time_marker now,start; while (now.diff_time(&start)<5.0) now.get_time(); } 
  274.  
  275.           if (base->input_state!=INPUT_RELOAD)
  276.             add_client_input((char *)use->packet_data(),use->packet_size(),found);
  277.  
  278.         }
  279.         else if (use->tick_received()==base->last_packet.tick_received())
  280.         {
  281.           if (prot->debug_level(net_protocol::DB_IMPORTANT_EVENT))
  282.             dprintf("(sending old %d)\n",use->tick_received());          
  283.  
  284.           // if they are sending stale data we need to send them the last packet so they can catchup
  285.           net_packet *pack=&base->last_packet;      
  286.           game_sock->write(pack->data,pack->packet_size()+pack->packet_prefix_size(),found->data_address); 
  287.  
  288.         } else if (prot->debug_level(net_protocol::DB_MAJOR_EVENT))
  289.           dprintf("received stale packet (got %d, expected %d)\n",use->tick_received(),base->current_tick);
  290.  
  291.       } else
  292.       {
  293.         if (prot->debug_level(net_protocol::DB_MAJOR_EVENT))
  294.         {
  295.           dprintf("received data from unknown client\n");
  296.           dprintf("from address "); from->print();
  297.           dprintf(" first addr "); player_list->data_address->print(); dprintf("\n");
  298.         }
  299.       }
  300.  
  301.     } else dprintf("received packet with bad checksum\n");
  302.       } else dprintf("received incomplete packet\n");
  303.     } else if (!from)
  304.       dprintf("received data and no from\n");
  305.     else if (!bytes_received)
  306.       dprintf("received 0 byte data\n");
  307.     ret=1;
  308.     if (from) delete from;
  309.  
  310.   }
  311.  
  312.  
  313.   /**************************       Any client with commands?       **************************/
  314.   player_client *c;
  315.   for (c=player_list;c;c=c->next)  
  316.     if (c->comm->error() || (c->comm->ready_to_read() && !process_client_command(c)))
  317.     {
  318.       c->set_delete_me(1);
  319.       check_collection_complete();
  320.     }
  321.     else ret=1;
  322.   
  323.   return 1;
  324. }
  325.  
  326.  
  327. int game_server::input_missing()
  328. {
  329.  
  330.   return 1;
  331. }
  332.  
  333.  
  334.  
  335. int game_server::end_reload(int disconnect)  // notify evryone you've reloaded the level (at server request)
  336. {  
  337.   player_client *c=player_list;
  338.   prot->select(0);
  339.  
  340.   for (;c;c=c->next) 
  341.     if (!c->delete_me() && c->wait_reload()) 
  342.     {
  343.       if (disconnect)
  344.         c->set_delete_me(1);
  345.       else return 0;
  346.     }
  347.  
  348.   for (c=player_list;c;c=c->next)   
  349.     c->set_has_joined(1);
  350.   reload_state=0;
  351.   
  352.   return 1;
  353. }
  354.  
  355. int game_server::start_reload()
  356. {
  357.   player_client *c=player_list;
  358.   reload_state=1;
  359.   prot->select(0);
  360.  
  361.   for (;c;c=c->next) 
  362.   {
  363.     if (!c->delete_me() && c->need_reload_start_ok())    // if the client is already waiting for reload state to start, send ok
  364.     {
  365.       uchar cmd=CLCMD_RELOAD_START;
  366.       if (c->comm->write(&cmd,1)!=1) { c->set_delete_me(1); }
  367.       c->set_need_reload_start_ok(0);
  368.     }
  369.     c->set_wait_reload(1);
  370.   }
  371.   return 1;
  372. }
  373.  
  374.  
  375. int game_server::isa_client(int client_id)
  376. {
  377.   player_client *c=player_list;
  378.   if (!client_id) return 1;
  379.   for (;c;c=c->next) if (c->client_id==client_id) return 1;
  380.   return 0;   
  381. }
  382.  
  383. int game_server::add_client(int type, net_socket *sock, net_address *from)
  384. {
  385.   if (type==CLIENT_ABUSE)
  386.   {
  387.  
  388.     if (total_players()>=main_net_cfg->max_players)
  389.     {
  390.       uchar too_many=2;
  391.       sock->write(&too_many,1);
  392.       return 0;
  393.     }
  394.  
  395.     uchar reg=registered ? 1 : 0;
  396.     if (sock->write(®,1)!=1)  
  397.       return 0;
  398.  
  399.  
  400.     ushort our_port=lstl(main_net_cfg->game_port),cport;
  401.     char name[256];
  402.     uchar len;
  403.     short nkills=lstl(main_net_cfg->kills);
  404.     
  405.     if (sock->read(&len,1)!=1 ||
  406.                 sock->read(name,len)!=len ||
  407.                 sock->read(&cport,2)!=2 ||
  408.         sock->write(&our_port,2)!=2 ||
  409.                 sock->write(&nkills,2)!=2)
  410.       return 0;
  411.  
  412.     cport=lstl(cport);
  413.  
  414.     
  415.     int f=-1,i;
  416.     for (i=0;f==-1 && i<MAX_JOINERS;i++)
  417.       if (!isa_client(i))
  418.       {
  419.         f=i;
  420.  
  421.                 join_struct *j=base->join_list;
  422.                 for (;j;j=j->next)
  423.                   if (j->client_id==i)
  424.                     f=-1;
  425.       }
  426.  
  427.  
  428.     if (f==-1) return 0;    
  429.  
  430.  
  431.     from->set_port(cport);
  432.  
  433.     ushort client_id=lstl(f);
  434.     if (sock->write(&client_id,2)!=2) { return 0; }
  435.     client_id=f;
  436.  
  437.     join_array[client_id].next=base->join_list;
  438.     base->join_list=&join_array[client_id];
  439.     join_array[client_id].client_id=client_id;
  440.     strcpy(join_array[client_id].name,name);   
  441.     player_list=new player_client(f,sock,from,player_list);
  442.  
  443.     return 1;
  444.   } else return 0;
  445. }
  446.  
  447. int game_server::kill_slackers()
  448. {
  449.   player_client *c=player_list;
  450.   for (;c;c=c->next)
  451.     if (c->wait_input())
  452.       c->set_delete_me(1);
  453.   check_collection_complete();  
  454.   return 1;
  455. }
  456.  
  457. int game_server::quit()
  458. {
  459.   player_client *c=player_list;  
  460.   while (c)
  461.   {
  462.     player_client *d=c;
  463.     c=c->next;
  464.     delete d;
  465.   }
  466.   player_list=NULL;
  467.   return 1;
  468. }
  469.  
  470.  
  471. game_server::~game_server()
  472. {
  473.   quit();
  474. }
  475.  
  476.